#!/usr/bin/env python3
import os
import re
import subprocess
import shutil
import time
import glob
from datetime import datetime
from itertools import product

class DMConfigTester:
    def __init__(self):
        self.original_config = "../init_dm8/dm.ini"
        self.backup_config = "../init_dm8/dm.ini.backup"
        self.test_log = "performance_test.log"
        self.results_csv = "test_results.csv"
        
        # 要测试的参数组合
        self.commit_batch_values = [10, 30, 60, 90, 120]
        self.commit_timeout_values = [1, 3, 5, 10, 15]
        
        # 确保备份文件存在
        if not os.path.exists(self.backup_config):
            shutil.copy2(self.original_config, self.backup_config)
    
    def generate_config(self, commit_batch, commit_timeout):
        """生成指定参数的配置文件"""
        print(f"生成配置: COMMIT_BATCH={commit_batch}, COMMIT_BATCH_TIMEOUT={commit_timeout}")
        
        # 读取原始配置
        with open(self.backup_config, 'r', encoding='utf-8') as f:
            content = f.read()
        
        # 替换参数
        content = self.replace_parameter(content, "COMMIT_BATCH", commit_batch)
        content = self.replace_parameter(content, "COMMIT_BATCH_TIMEOUT", commit_timeout)
        
        # 写入新配置
        with open(self.original_config, 'w', encoding='utf-8') as f:
            f.write(content)
        
        return True
    
    def replace_parameter(self, content, param_name, new_value):
        """替换配置文件中的参数值"""
        lines = content.split('\n')
        new_lines = []
        param_found = False
        
        for line in lines:
            if line.strip().startswith(f"{param_name}="):
                # 替换参数值
                new_line = f"{param_name}={new_value}"
                new_lines.append(new_line)
                param_found = True
            else:
                new_lines.append(line)
        
        # 如果参数不存在，添加到文件末尾
        if not param_found:
            new_lines.append(f"{param_name}={new_value}")
        
        return '\n'.join(new_lines)
    
    def run_test_suite(self):
        """运行测试套件 - 只执行4条核心命令"""
        commands = [
            "sh ../init_dm8/1initDB.sh",
            "sh tpcc_load.sh",
            "sh tpcc_test.sh"
        ]
        
        print("开始执行测试套件...")
        
        for cmd in commands:
            print(f"执行命令: {cmd}")
            try:
                result = subprocess.run(cmd, shell=True, check=True, 
                                      stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                                      text=True, timeout=3600)  # 1小时超时
                print(f"命令执行成功: {cmd}")
            except subprocess.CalledProcessError as e:
                print(f"命令执行失败: {cmd}")
                print(f"错误输出: {e.stderr}")
                return False
            except subprocess.TimeoutExpired:
                print(f"命令执行超时: {cmd}")
                return False
        
        return True
    
    def get_tpcc_result(self):
        """获取TPCC测试结果"""
        try:
            # 构建获取最新TPCC日志文件的命令
            get_latest_log_cmd = 'ls -lort log/01_tpcc/ | tail -n 1 | awk \'{print $NF}\''
            result = subprocess.run(get_latest_log_cmd, shell=True, 
                                  stdout=subprocess.PIPE, text=True)
            
            if result.returncode == 0:
                latest_log = result.stdout.strip()
                log_path = f"log/01_tpcc/{latest_log}"
                
                if os.path.exists(log_path):
                    # 使用grep命令提取TPCC结果
                    grep_cmd = f'grep -A 4 "Measured tpmC (NewOrders)" {log_path}'
                    grep_result = subprocess.run(grep_cmd, shell=True,
                                               stdout=subprocess.PIPE, text=True)
                    
                    if grep_result.returncode == 0:
                        return grep_result.stdout.strip()
                    else:
                        return "TPCC结果提取失败"
                else:
                    return f"日志文件不存在: {log_path}"
            else:
                return "无法找到最新日志文件"
                
        except Exception as e:
            return f"获取TPCC结果时发生错误: {e}"
    
    def log_test_result(self, batch, timeout, tpcc_result):
        """记录测试结果"""
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        
        # 记录到详细日志
        with open(self.test_log, 'a', encoding='utf-8') as f:
            f.write(f"\n{'='*60}\n")
            f.write(f"测试时间: {timestamp}\n")
            f.write(f"配置参数: COMMIT_BATCH={batch}, COMMIT_BATCH_TIMEOUT={timeout}\n")
            f.write(f"TPCC结果:\n{tpcc_result}\n")
        
        # 提取TPMC数值
        tpmc_value = "N/A"
        tpmc_match = re.search(r"Measured tpmC \(NewOrders\)\s*:\s*([\d.]+)", tpcc_result)
        if tpmc_match:
            tpmc_value = tpmc_match.group(1)
        
        # 记录到CSV文件
        csv_header = False
        if not os.path.exists(self.results_csv):
            csv_header = True
        
        with open(self.results_csv, 'a', encoding='utf-8') as f:
            if csv_header:
                f.write("timestamp,commit_batch,commit_timeout,tpmc,raw_result\n")
            
            # 转义引号以便在CSV中正确存储
            safe_result = tpcc_result.replace('"', '""').replace('\n', ' ')
            
            f.write(f'{timestamp},{batch},{timeout},{tpmc_value},"{safe_result}"\n')
    
    def run_all_tests(self):
        """运行所有测试组合"""
        print("开始性能测试...")
        print("=" * 60)
        
        total_tests = len(self.commit_batch_values) * len(self.commit_timeout_values)
        current_test = 1
        
        for batch, timeout in product(self.commit_batch_values, self.commit_timeout_values):
            print(f"\n运行测试 {current_test}/{total_tests}")
            print(f"参数: COMMIT_BATCH={batch}, COMMIT_BATCH_TIMEOUT={timeout}")
            
            # 生成配置
            self.generate_config(batch, timeout)
            
            # 运行测试套件
            test_success = self.run_test_suite()
            
            if test_success:
                # 获取TPCC结果
                tpcc_result = self.get_tpcc_result()
                
                # 记录结果
                self.log_test_result(batch, timeout, tpcc_result)
                
                print(f"TPCC结果:\n{tpcc_result}")
                print(f"测试完成，结果已记录")
            else:
                print(f"测试失败，跳过结果记录")
            
            current_test += 1
            
            # 短暂暂停，避免资源冲突
            time.sleep(2)
        
        print("\n所有测试完成！")
        print(f"详细日志: {self.test_log}")
        print(f"CSV结果: {self.results_csv}")
    
    def cleanup(self):
        """清理，恢复原始配置"""
        if os.path.exists(self.backup_config):
            shutil.copy2(self.backup_config, self.original_config)
            print("已恢复原始配置文件")

if __name__ == "__main__":
    tester = DMConfigTester()
    
    try:
        tester.run_all_tests()
    except KeyboardInterrupt:
        print("\n测试被用户中断")
    except Exception as e:
        print(f"测试过程中发生错误: {e}")
    finally:
        tester.cleanup()
